package com.sevenwonders.core;

import java.util.ArrayList;
import java.util.List;

import com.sevenwonders.core.City.WonderPhase;
import com.sevenwonders.core.Player.VictoryPointCategory;

public enum BaseCard {
    LUMBER_YARD {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Lumber Yard", CardType.RAW_MATERIALS, this));
            }
            if (numPlayers >= 4) {
                cards.add(new Card(id_sequence++, "Lumber Yard", CardType.RAW_MATERIALS, this));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addTradeableResource(Resource.WOOD);
        }
    },
    STONE_PIT {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Stone Pit", CardType.RAW_MATERIALS, this));
            }
            if (numPlayers >= 5) {
                cards.add(new Card(id_sequence++, "Stone Pit", CardType.RAW_MATERIALS, this));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addTradeableResource(Resource.STONE);
        }
    },
    CLAY_POOL {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Clay Pool", CardType.RAW_MATERIALS, this));
            }
            if (numPlayers >= 5) {
                cards.add(new Card(id_sequence++, "Clay Pool", CardType.RAW_MATERIALS, this));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addTradeableResource(Resource.CLAY);
        }
    },
    ORE_VEIN {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Ore Vein", CardType.RAW_MATERIALS, this));
            }
            if (numPlayers >= 4) {
                cards.add(new Card(id_sequence++, "Ore Vein", CardType.RAW_MATERIALS, this));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addTradeableResource(Resource.ORE);
        }
    },
    TREE_FARM {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 6) {
                cards.add(new Card(id_sequence++, "Tree Farm", CardType.RAW_MATERIALS, this).setCostCoin(1));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addTradeableComboResource(Resource.WOOD_CLAY);
        }
    },
    EXCAVATION {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 4) {
                cards.add(new Card(id_sequence++, "Excavation", CardType.RAW_MATERIALS, this).setCostCoin(1));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addTradeableComboResource(Resource.STONE_CLAY);
        }
    },
    CLAY_PIT {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Clay Pit", CardType.RAW_MATERIALS, this).setCostCoin(1));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addTradeableComboResource(Resource.CLAY_ORE);
        }
    },
    TIMBER_YARD {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Timber Yard", CardType.RAW_MATERIALS, this).setCostCoin(1));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addTradeableComboResource(Resource.STONE_WOOD);
        }
    },
    FOREST_CAVE {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 5) {
                cards.add(new Card(id_sequence++, "Forest Cave", CardType.RAW_MATERIALS, this).setCostCoin(1));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addTradeableComboResource(Resource.WOOD_ORE);
        }
    },
    MINE {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 6) {
                cards.add(new Card(id_sequence++, "Mine", CardType.RAW_MATERIALS, this).setCostCoin(1));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addTradeableComboResource(Resource.ORE_STONE);
        }
    },
    SAWMILL {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Sawmill", CardType.RAW_MATERIALS, this).setCostCoin(1));
            }
            if (numPlayers >= 4) {
                cards.add(new Card(id_sequence++, "Sawmill", CardType.RAW_MATERIALS, this).setCostCoin(1));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addTradeableResource(Resource.WOOD);
            player.addTradeableResource(Resource.WOOD);
        }
    },
    QUARRY {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Quarry", CardType.RAW_MATERIALS, this).setCostCoin(1));
            }
            if (numPlayers >= 4) {
                cards.add(new Card(id_sequence++, "Quarry", CardType.RAW_MATERIALS, this).setCostCoin(1));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addTradeableResource(Resource.STONE);
            player.addTradeableResource(Resource.STONE);
        }
    },
    BRICKYARD {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Brickyard", CardType.RAW_MATERIALS, this).setCostCoin(1));
            }
            if (numPlayers >= 4) {
                cards.add(new Card(id_sequence++, "Brickyard", CardType.RAW_MATERIALS, this).setCostCoin(1));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addTradeableResource(Resource.CLAY);
            player.addTradeableResource(Resource.CLAY);
        }
    },
    FOUNDRY {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Foundry", CardType.RAW_MATERIALS, this).setCostCoin(1));
            }
            if (numPlayers >= 4) {
                cards.add(new Card(id_sequence++, "Foundry", CardType.RAW_MATERIALS, this).setCostCoin(1));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addTradeableResource(Resource.ORE);
            player.addTradeableResource(Resource.ORE);
        }
    },
    LOOM {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Loom", CardType.MANUFACTURED_GOODS, this));
            }
            if (numPlayers >= (age == 1 ? 6 : 5)) {
                cards.add(new Card(id_sequence++, "Loom", CardType.MANUFACTURED_GOODS, this));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addTradeableResource(Resource.CLOTH);
        }
    },
    GLASSWORKS {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Glassworks", CardType.MANUFACTURED_GOODS, this));
            }
            if (numPlayers >= (age == 1 ? 6 : 5)) {
                cards.add(new Card(id_sequence++, "Glassworks", CardType.MANUFACTURED_GOODS, this));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addTradeableResource(Resource.GLASS);
        }
    },
    PRESS {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Press", CardType.MANUFACTURED_GOODS, this));
            }
            if (numPlayers >= (age == 1 ? 6 : 5)) {
                cards.add(new Card(id_sequence++, "Press", CardType.MANUFACTURED_GOODS, this));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addTradeableResource(Resource.PAPYRUS);
        }
    },
    PAWNSHOP {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 4) {
                cards.add(new Card(id_sequence++, "Pawnshop", CardType.CIVILIAN, this));
            }
            if (numPlayers >= 7) {
                cards.add(new Card(id_sequence++, "Pawnshop", CardType.CIVILIAN, this));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addVictoryPoints(VictoryPointCategory.CIVILIAN, 3);
        }
    },
    BATHS {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Baths", CardType.CIVILIAN, this).setCostResource(Resource.STONE)
                    .setChain("Aqueduct"));
            }
            if (numPlayers >= 7) {
                cards.add(new Card(id_sequence++, "Baths", CardType.CIVILIAN, this).setCostResource(Resource.STONE)
                    .setChain("Aqueduct"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addVictoryPoints(VictoryPointCategory.CIVILIAN, 3);
        }
    },
    ALTAR {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Altar", CardType.CIVILIAN, this).setChain("Temple"));
            }
            if (numPlayers >= 5) {
                cards.add(new Card(id_sequence++, "Altar", CardType.CIVILIAN, this).setChain("Temple"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addVictoryPoints(VictoryPointCategory.CIVILIAN, 2);
        }
    },
    THEATER {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Theater", CardType.CIVILIAN, this).setChain("Statue"));
            }
            if (numPlayers >= 6) {
                cards.add(new Card(id_sequence++, "Theater", CardType.CIVILIAN, this).setChain("Statue"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addVictoryPoints(VictoryPointCategory.CIVILIAN, 2);
        }
    },
    AQUEDUCT {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Aqueduct", CardType.CIVILIAN, this).setCostResource(Resource.STONE, Resource.STONE, Resource.STONE)
                    .setCostCard("Baths"));
            }
            if (numPlayers >= 7) {
                cards.add(new Card(id_sequence++, "Aqueduct", CardType.CIVILIAN, this).setCostResource(Resource.STONE, Resource.STONE, Resource.STONE)
                    .setCostCard("Baths"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addVictoryPoints(VictoryPointCategory.CIVILIAN, 5);
        }
    },
    TEMPLE {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Temple", CardType.CIVILIAN, this).setCostResource(Resource.WOOD, Resource.CLAY, Resource.GLASS)
                    .setCostCard("Altar")
                    .setChain("Pantheon"));
            }
            if (numPlayers >= 6) {
                cards.add(new Card(id_sequence++, "Temple", CardType.CIVILIAN, this).setCostResource(Resource.WOOD, Resource.CLAY, Resource.GLASS)
                    .setCostCard("Altar")
                    .setChain("Pantheon"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addVictoryPoints(VictoryPointCategory.CIVILIAN, 3);
        }
    },
    STATUE {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Statue", CardType.CIVILIAN, this).setCostResource(Resource.WOOD, Resource.ORE, Resource.ORE)
                    .setCostCard("Theater")
                    .setChain("Gardens"));
            }
            if (numPlayers >= 7) {
                cards.add(new Card(id_sequence++, "Statue", CardType.CIVILIAN, this).setCostResource(Resource.WOOD, Resource.ORE, Resource.ORE)
                    .setCostCard("Theater")
                    .setChain("Gardens"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addVictoryPoints(VictoryPointCategory.CIVILIAN, 4);
        }
    },
    COURTHOUSE {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Courthouse", CardType.CIVILIAN, this).setCostResource(Resource.CLAY, Resource.CLAY, Resource.CLOTH)
                    .setCostCard("Scriptorium"));
            }
            if (numPlayers >= 5) {
                cards.add(new Card(id_sequence++, "Courthouse", CardType.CIVILIAN, this).setCostResource(Resource.CLAY, Resource.CLAY, Resource.CLOTH)
                    .setCostCard("Scriptorium"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addVictoryPoints(VictoryPointCategory.CIVILIAN, 4);
        }
    },
    PANTHEON {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Pantheon", CardType.CIVILIAN, this).setCostResource(Resource.CLAY, Resource.CLAY, Resource.ORE,
                    Resource.PAPYRUS, Resource.CLOTH, Resource.GLASS)
                    .setCostCard("Temple"));
            }
            if (numPlayers >= 6) {
                cards.add(new Card(id_sequence++, "Pantheon", CardType.CIVILIAN, this).setCostResource(Resource.CLAY, Resource.CLAY, Resource.ORE,
                    Resource.PAPYRUS, Resource.CLOTH, Resource.GLASS)
                    .setCostCard("Temple"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addVictoryPoints(VictoryPointCategory.CIVILIAN, 7);
        }
    },
    GARDENS {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Gardens", CardType.CIVILIAN, this).setCostResource(Resource.WOOD, Resource.CLAY, Resource.CLAY)
                    .setCostCard("Statue"));
            }
            if (numPlayers >= 4) {
                cards.add(new Card(id_sequence++, "Gardens", CardType.CIVILIAN, this).setCostResource(Resource.WOOD, Resource.CLAY, Resource.CLAY)
                    .setCostCard("Statue"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addVictoryPoints(VictoryPointCategory.CIVILIAN, 5);
        }
    },
    TOWN_HALL {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Town Hall", CardType.CIVILIAN, this).setCostResource(Resource.STONE, Resource.STONE, Resource.ORE,
                    Resource.GLASS));
            }
            if (numPlayers >= 5) {
                cards.add(new Card(id_sequence++, "Town Hall", CardType.CIVILIAN, this).setCostResource(Resource.STONE, Resource.STONE, Resource.ORE,
                    Resource.GLASS));
            }
            if (numPlayers >= 6) {
                cards.add(new Card(id_sequence++, "Town Hall", CardType.CIVILIAN, this).setCostResource(Resource.STONE, Resource.STONE, Resource.ORE,
                    Resource.GLASS));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addVictoryPoints(VictoryPointCategory.CIVILIAN, 6);
        }
    },
    PALACE {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Palace", CardType.CIVILIAN, this).setCostResource(Resource.STONE, Resource.ORE, Resource.WOOD,
                    Resource.CLAY, Resource.PAPYRUS, Resource.CLOTH, Resource.GLASS));
            }
            if (numPlayers >= 7) {
                cards.add(new Card(id_sequence++, "Palace", CardType.CIVILIAN, this).setCostResource(Resource.STONE, Resource.ORE, Resource.WOOD,
                    Resource.CLAY, Resource.PAPYRUS, Resource.CLOTH, Resource.GLASS));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addVictoryPoints(VictoryPointCategory.CIVILIAN, 8);
        }
    },
    SENATE {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Senate", CardType.CIVILIAN, this).setCostResource(Resource.ORE, Resource.STONE, Resource.STONE,
                    Resource.WOOD)
                    .setCostCard("Library"));
            }
            if (numPlayers >= 5) {
                cards.add(new Card(id_sequence++, "Senate", CardType.CIVILIAN, this).setCostResource(Resource.ORE, Resource.STONE, Resource.STONE,
                    Resource.WOOD)
                    .setCostCard("Library"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addVictoryPoints(VictoryPointCategory.CIVILIAN, 6);
        }
    },
    TAVERN {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 4) {
                cards.add(new Card(id_sequence++, "Tavern", CardType.COMMERCIAL, this));
            }
            if (numPlayers >= 5) {
                cards.add(new Card(id_sequence++, "Tavern", CardType.COMMERCIAL, this));
            }
            if (numPlayers >= 7) {
                cards.add(new Card(id_sequence++, "Tavern", CardType.COMMERCIAL, this));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addMoney(5);
        }
    },
    EAST_TRADING_POST {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "East Trading Post", CardType.COMMERCIAL, this).setChain("Forum"));
            }
            if (numPlayers >= 7) {
                cards.add(new Card(id_sequence++, "East Trading Post", CardType.COMMERCIAL, this).setChain("Forum"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            // TODO:  Check for East Trading Post card in play when doing commerce
        }
    },
    WEST_TRADING_POST {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "West Trading Post", CardType.COMMERCIAL, this).setChain("Forum"));
            }
            if (numPlayers >= 7) {
                cards.add(new Card(id_sequence++, "West Trading Post", CardType.COMMERCIAL, this).setChain("Forum"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            // TODO:  Check for West Trading Post card in play when doing commerce
        }
    },
    MARKETPLACE {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Marketplace", CardType.COMMERCIAL, this).setChain("Caravansery"));
            }
            if (numPlayers >= 6) {
                cards.add(new Card(id_sequence++, "Marketplace", CardType.COMMERCIAL, this).setChain("Caravansery"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            // Nothing needs to be done here
        }
    },
    FORUM {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Forum", CardType.COMMERCIAL, this).setCostResource(Resource.CLAY, Resource.CLAY)
                    .setCostCard("Trading Post")
                    .setChain("Haven"));
            }
            if (numPlayers >= 6) {
                cards.add(new Card(id_sequence++, "Forum", CardType.COMMERCIAL, this).setCostResource(Resource.CLAY, Resource.CLAY)
                    .setCostCard("Trading Post")
                    .setChain("Haven"));
            }
            if (numPlayers >= 7) {
                cards.add(new Card(id_sequence++, "Forum", CardType.COMMERCIAL, this).setCostResource(Resource.CLAY, Resource.CLAY)
                    .setCostCard("Trading Post")
                    .setChain("Haven"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addComboResource(Resource.MANUFACTURED);
        }
    },
    CARAVANSERY {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Caravansery", CardType.COMMERCIAL, this).setCostResource(Resource.CLAY, Resource.CLAY)
                    .setCostCard("Marketplace")
                    .setChain("Lighthouse"));
            }
            if (numPlayers >= 5) {
                cards.add(new Card(id_sequence++, "Caravansery", CardType.COMMERCIAL, this).setCostResource(Resource.WOOD, Resource.WOOD)
                    .setCostCard("Marketplace")
                    .setChain("Lighthouse"));
            }
            if (numPlayers >= 6) {
                cards.add(new Card(id_sequence++, "Caravansery", CardType.COMMERCIAL, this).setCostResource(Resource.WOOD, Resource.WOOD)
                    .setCostCard("Marketplace")
                    .setChain("Lighthouse"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addComboResource(Resource.RAW);
        }
    },
    VINEYARD {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Vineyard", CardType.COMMERCIAL, this));
            }
            if (numPlayers >= 6) {
                cards.add(new Card(id_sequence++, "Vineyard", CardType.COMMERCIAL, this));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addMoney(player.getCardCount(CardType.RAW_MATERIALS));

            for (Player neighbor : Game.myGame.getNeighbors(player)) {
                player.addMoney(neighbor.getCardCount(CardType.RAW_MATERIALS));
            }
        }
    },
    BAZAR {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 4) {
                cards.add(new Card(id_sequence++, "Bazar", CardType.COMMERCIAL, this));
            }
            if (numPlayers >= 7) {
                cards.add(new Card(id_sequence++, "Bazar", CardType.COMMERCIAL, this));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addMoney(player.getCardCount(CardType.MANUFACTURED_GOODS) * 2);

            for (Player neighbor : Game.myGame.getNeighbors(player)) {
                player.addMoney(neighbor.getCardCount(CardType.MANUFACTURED_GOODS) * 2);
            }
        }
    },
    HAVEN {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Haven", CardType.COMMERCIAL, this).setCostResource(Resource.WOOD, Resource.ORE, Resource.CLOTH)
                    .setCostCard("Forum"));
            }
            if (numPlayers >= 4) {
                cards.add(new Card(id_sequence++, "Haven", CardType.COMMERCIAL, this).setCostResource(Resource.WOOD, Resource.ORE, Resource.CLOTH)
                    .setCostCard("Forum"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            int count = player.getCardCount(CardType.RAW_MATERIALS);
            player.addMoney(count);
            player.addVictoryPoints(VictoryPointCategory.COMMERCIAL, count);
        }
    },
    LIGHTHOUSE {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Lighthouse", CardType.COMMERCIAL, this).setCostResource(Resource.STONE, Resource.GLASS)
                    .setCostCard("Caravansery"));
            }
            if (numPlayers >= 6) {
                cards.add(new Card(id_sequence++, "Lighthouse", CardType.COMMERCIAL, this).setCostResource(Resource.STONE, Resource.GLASS)
                    .setCostCard("Caravansery"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            int count = player.getCardCount(CardType.COMMERCIAL);
            player.addMoney(count);
            player.addVictoryPoints(VictoryPointCategory.COMMERCIAL, count);
        }
    },
    CHAMBER_OF_COMMERCE {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 4) {
                cards.add(new Card(id_sequence++, "Chamber of Commerce", CardType.COMMERCIAL, this).setCostResource(Resource.CLAY, Resource.CLAY,
                    Resource.PAPYRUS));
            }
            if (numPlayers >= 6) {
                cards.add(new Card(id_sequence++, "Chamber of Commerce", CardType.COMMERCIAL, this).setCostResource(Resource.CLAY, Resource.CLAY,
                    Resource.PAPYRUS));
            }
            return cards;
        }

        void awardBonus(Player player) {
            int count = player.getCardCount(CardType.MANUFACTURED_GOODS) * 2;
            player.addMoney(count);
            player.addVictoryPoints(VictoryPointCategory.COMMERCIAL, count);
        }
    },
    ARENA {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Arena", CardType.COMMERCIAL, this).setCostResource(Resource.STONE, Resource.STONE, Resource.ORE)
                    .setCostCard("Dispensary"));
            }
            if (numPlayers >= 5) {
                cards.add(new Card(id_sequence++, "Arena", CardType.COMMERCIAL, this).setCostResource(Resource.STONE, Resource.STONE, Resource.ORE)
                    .setCostCard("Dispensary"));
            }
            if (numPlayers >= 7) {
                cards.add(new Card(id_sequence++, "Arena", CardType.COMMERCIAL, this).setCostResource(Resource.STONE, Resource.STONE, Resource.ORE)
                    .setCostCard("Dispensary"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            for (WonderPhase wonderPhase : player.getCity()
                .getWonderPhasesForSide()) {

                if (wonderPhase.isCompleted()) {
                    player.addMoney(3);
                    player.addVictoryPoints(VictoryPointCategory.WONDER, 1);
                }
            }
        }
    },
    STOCKADE {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Stockade", CardType.MILITARY, this).setCostResource(Resource.WOOD));
            }
            if (numPlayers >= 7) {
                cards.add(new Card(id_sequence++, "Stockade", CardType.MILITARY, this).setCostResource(Resource.WOOD));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addMilitary(1);
        }
    },
    BARRACKS {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Barracks", CardType.MILITARY, this).setCostResource(Resource.ORE));
            }
            if (numPlayers >= 5) {
                cards.add(new Card(id_sequence++, "Barracks", CardType.MILITARY, this).setCostResource(Resource.ORE));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addMilitary(1);
        }
    },
    GUARD_TOWER {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Guard Tower", CardType.MILITARY, this).setCostResource(Resource.CLAY));
            }
            if (numPlayers >= 4) {
                cards.add(new Card(id_sequence++, "Guard Tower", CardType.MILITARY, this).setCostResource(Resource.CLAY));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addMilitary(1);
        }
    },
    WALLS {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Walls", CardType.MILITARY, this).setCostResource(Resource.STONE, Resource.STONE, Resource.STONE)
                    .setChain("Fortifications"));
            }
            if (numPlayers >= 7) {
                cards.add(new Card(id_sequence++, "Walls", CardType.MILITARY, this).setCostResource(Resource.STONE, Resource.STONE, Resource.STONE)
                    .setChain("Fortifications"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addMilitary(2);
        }
    },
    TRAINING_GROUND {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 4) {
                cards.add(new Card(id_sequence++, "Training Ground", CardType.MILITARY, this).setCostResource(Resource.WOOD, Resource.ORE, Resource.ORE)
                    .setChain("Circus"));
            }
            if (numPlayers >= 6) {
                cards.add(new Card(id_sequence++, "Training Ground", CardType.MILITARY, this).setCostResource(Resource.WOOD, Resource.ORE, Resource.ORE)
                    .setChain("Circus"));
            }
            if (numPlayers >= 7) {
                cards.add(new Card(id_sequence++, "Training Ground", CardType.MILITARY, this).setCostResource(Resource.WOOD, Resource.ORE, Resource.ORE)
                    .setChain("Circus"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addMilitary(2);
        }
    },
    STABLES {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Stables", CardType.MILITARY, this).setCostResource(Resource.ORE, Resource.CLAY, Resource.WOOD)
                    .setCostCard("Apothecary"));
            }
            if (numPlayers >= 5) {
                cards.add(new Card(id_sequence++, "Stables", CardType.MILITARY, this).setCostResource(Resource.ORE, Resource.CLAY, Resource.WOOD)
                    .setCostCard("Apothecary"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addMilitary(2);
        }
    },
    ARCHERY_RANGE {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Archery Range", CardType.MILITARY, this).setCostResource(Resource.WOOD, Resource.WOOD, Resource.ORE)
                    .setCostCard("Workshop"));
            }
            if (numPlayers >= 6) {
                cards.add(new Card(id_sequence++, "Archery Range", CardType.MILITARY, this).setCostResource(Resource.WOOD, Resource.WOOD, Resource.ORE)
                    .setCostCard("Workshop"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addMilitary(2);
        }
    },
    FORTIFICATIONS {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Fortifications", CardType.MILITARY, this).setCostResource(Resource.STONE, Resource.ORE, Resource.ORE,
                    Resource.ORE)
                    .setCostCard("Walls"));
            }
            if (numPlayers >= 7) {
                cards.add(new Card(id_sequence++, "Fortifications", CardType.MILITARY, this).setCostResource(Resource.STONE, Resource.ORE, Resource.ORE,
                    Resource.ORE)
                    .setCostCard("Walls"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addMilitary(3);
        }
    },
    CIRCUS {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Circus", CardType.MILITARY, this).setCostResource(Resource.STONE, Resource.STONE, Resource.STONE,
                    Resource.ORE)
                    .setCostCard("Training Grounds"));
            }
            if (numPlayers >= 5) {
                cards.add(new Card(id_sequence++, "Circus", CardType.MILITARY, this).setCostResource(Resource.STONE, Resource.STONE, Resource.STONE,
                    Resource.ORE)
                    .setCostCard("Training Grounds"));
            }
            if (numPlayers >= 6) {
                cards.add(new Card(id_sequence++, "Circus", CardType.MILITARY, this).setCostResource(Resource.STONE, Resource.STONE, Resource.STONE,
                    Resource.ORE)
                    .setCostCard("Training Grounds"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addMilitary(3);
        }
    },
    ARSENAL {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Arsenal", CardType.MILITARY, this).setCostResource(Resource.ORE, Resource.WOOD, Resource.WOOD,
                    Resource.CLOTH));
            }
            if (numPlayers >= 5) {
                cards.add(new Card(id_sequence++, "Arsenal", CardType.MILITARY, this).setCostResource(Resource.ORE, Resource.WOOD, Resource.WOOD,
                    Resource.CLOTH));
            }
            if (numPlayers >= 6) {
                cards.add(new Card(id_sequence++, "Arsenal", CardType.MILITARY, this).setCostResource(Resource.ORE, Resource.WOOD, Resource.WOOD,
                    Resource.CLOTH));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addMilitary(3);
        }
    },
    SIEGE_WORKSHOP {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Siege Workshop", CardType.MILITARY, this).setCostResource(Resource.WOOD, Resource.CLAY, Resource.CLAY,
                    Resource.CLAY)
                    .setCostCard("Laboratory"));
            }
            if (numPlayers >= 5) {
                cards.add(new Card(id_sequence++, "Siege Workshop", CardType.MILITARY, this).setCostResource(Resource.WOOD, Resource.CLAY, Resource.CLAY,
                    Resource.CLAY)
                    .setCostCard("Laboratory"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addMilitary(3);
        }
    },
    APOTHECARY {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Apothecary", CardType.SCIENTIFIC, this).setCostResource(Resource.CLOTH)
                    .setChain("Stables", "Dispensary"));
            }
            if (numPlayers >= 5) {
                cards.add(new Card(id_sequence++, "Apothecary", CardType.SCIENTIFIC, this).setCostResource(Resource.CLOTH)
                    .setChain("Stables", "Dispensary"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addScience(Science.MATHEMATICS);
        }
    },
    WORKSHOP {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Workshop", CardType.SCIENTIFIC, this).setCostResource(Resource.GLASS)
                    .setChain("Archery Range", "Laboratory"));
            }
            if (numPlayers >= 7) {
                cards.add(new Card(id_sequence++, "Workshop", CardType.SCIENTIFIC, this).setCostResource(Resource.GLASS)
                    .setChain("Archery Range", "Laboratory"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addScience(Science.ENGINEERING);
        }
    },
    SCRIPTORIUM {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Scriptorium", CardType.SCIENTIFIC, this).setCostResource(Resource.PAPYRUS)
                    .setChain("Courthouse", "Library"));
            }
            if (numPlayers >= 4) {
                cards.add(new Card(id_sequence++, "Scriptorium", CardType.SCIENTIFIC, this).setCostResource(Resource.PAPYRUS)
                    .setChain("Courthouse", "Library"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addScience(Science.WRITING);
        }
    },
    DISPENSARY {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Dispensary", CardType.SCIENTIFIC, this).setCostResource(Resource.ORE, Resource.ORE, Resource.GLASS)
                    .setCostCard("Apothecary")
                    .setChain("Arena", "Lodge"));
            }
            if (numPlayers >= 4) {
                cards.add(new Card(id_sequence++, "Dispensary", CardType.SCIENTIFIC, this).setCostResource(Resource.ORE, Resource.ORE, Resource.GLASS)
                    .setCostCard("Apothecary")
                    .setChain("Arena", "Lodge"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addScience(Science.MATHEMATICS);
        }
    },
    LABORATORY {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Laboratory", CardType.SCIENTIFIC, this).setCostResource(Resource.CLAY, Resource.CLAY, Resource.PAPYRUS)
                    .setCostCard("Workshop")
                    .setChain("Siege Workshop", "Observatory"));
            }
            if (numPlayers >= 5) {
                cards.add(new Card(id_sequence++, "Laboratory", CardType.SCIENTIFIC, this).setCostResource(Resource.CLAY, Resource.CLAY, Resource.PAPYRUS)
                    .setCostCard("Workshop")
                    .setChain("Siege Workshop", "Observatory"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addScience(Science.ENGINEERING);
        }
    },
    LIBRARY {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Library", CardType.SCIENTIFIC, this).setCostResource(Resource.STONE, Resource.STONE, Resource.CLOTH)
                    .setCostCard("Scriptorium")
                    .setChain("Senate", "University"));
            }
            if (numPlayers >= 6) {
                cards.add(new Card(id_sequence++, "Library", CardType.SCIENTIFIC, this).setCostResource(Resource.STONE, Resource.STONE, Resource.CLOTH)
                    .setCostCard("Scriptorium")
                    .setChain("Senate", "University"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addScience(Science.WRITING);
        }
    },
    SCHOOL {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "School", CardType.SCIENTIFIC, this).setCostResource(Resource.WOOD, Resource.PAPYRUS)
                    .setChain("Academy", "Study"));
            }
            if (numPlayers >= 7) {
                cards.add(new Card(id_sequence++, "School", CardType.SCIENTIFIC, this).setCostResource(Resource.WOOD, Resource.PAPYRUS)
                    .setChain("Academy", "Study"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addScience(Science.WRITING);
        }
    },
    LODGE {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Lodge", CardType.SCIENTIFIC, this).setCostResource(Resource.CLAY, Resource.CLAY, Resource.CLOTH,
                    Resource.PAPYRUS)
                    .setCostCard("Dispensary"));
            }
            if (numPlayers >= 6) {
                cards.add(new Card(id_sequence++, "Lodge", CardType.SCIENTIFIC, this).setCostResource(Resource.CLAY, Resource.CLAY, Resource.CLOTH,
                    Resource.PAPYRUS)
                    .setCostCard("Dispensary"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addScience(Science.MATHEMATICS);
        }
    },
    OBSERVATORY {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Observatory", CardType.SCIENTIFIC, this).setCostResource(Resource.ORE, Resource.ORE, Resource.GLASS,
                    Resource.CLOTH)
                    .setCostCard("Laboratory"));
            }
            if (numPlayers >= 7) {
                cards.add(new Card(id_sequence++, "Observatory", CardType.SCIENTIFIC, this).setCostResource(Resource.ORE, Resource.ORE, Resource.GLASS,
                    Resource.CLOTH)
                    .setCostCard("Laboratory"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addScience(Science.ENGINEERING);
        }
    },
    UNIVERSITY {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "University", CardType.SCIENTIFIC, this).setCostResource(Resource.WOOD, Resource.WOOD, Resource.PAPYRUS,
                    Resource.GLASS)
                    .setCostCard("Library"));
            }
            if (numPlayers >= 4) {
                cards.add(new Card(id_sequence++, "University", CardType.SCIENTIFIC, this).setCostResource(Resource.WOOD, Resource.WOOD, Resource.PAPYRUS,
                    Resource.GLASS)
                    .setCostCard("Library"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addScience(Science.WRITING);
        }
    },
    ACADEMY {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Academy", CardType.SCIENTIFIC, this).setCostResource(Resource.STONE, Resource.STONE, Resource.STONE,
                    Resource.GLASS)
                    .setCostCard("School"));
            }
            if (numPlayers >= 7) {
                cards.add(new Card(id_sequence++, "Academy", CardType.SCIENTIFIC, this).setCostResource(Resource.STONE, Resource.STONE, Resource.STONE,
                    Resource.GLASS)
                    .setCostCard("School"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addScience(Science.MATHEMATICS);
        }
    },
    STUDY {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            if (numPlayers >= 3) {
                cards.add(new Card(id_sequence++, "Study", CardType.SCIENTIFIC, this).setCostResource(Resource.WOOD, Resource.PAPYRUS, Resource.CLOTH)
                    .setCostCard("School"));
            }
            if (numPlayers >= 5) {
                cards.add(new Card(id_sequence++, "Study", CardType.SCIENTIFIC, this).setCostResource(Resource.WOOD, Resource.PAPYRUS, Resource.CLOTH)
                    .setCostCard("School"));
            }
            return cards;
        }

        void awardBonus(Player player) {
            player.addScience(Science.ENGINEERING);
        }
    },
    WORKERS_GUILD {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            cards.add(new Card(id_sequence++, "Workers Guild", CardType.GUILD, this).setCostResource(Resource.ORE, Resource.ORE, Resource.CLAY, Resource.STONE,
                Resource.WOOD));
            return cards;
        }

        void awardBonus(Player player) {
            for (Player neighbor : Game.myGame.getNeighbors(player)) {
                player.addVictoryPoints(VictoryPointCategory.GUILD, neighbor.getCardCount(CardType.RAW_MATERIALS));
            }
        }
    },
    CRAFTMENS_GUILD {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            cards.add(new Card(id_sequence++, "Craftmens Guild", CardType.GUILD, this).setCostResource(Resource.ORE, Resource.ORE, Resource.STONE,
                Resource.STONE));
            return cards;
        }

        void awardBonus(Player player) {
            for (Player neighbor : Game.myGame.getNeighbors(player)) {
                player.addVictoryPoints(VictoryPointCategory.GUILD, neighbor.getCardCount(CardType.MANUFACTURED_GOODS) * 2);
            }
        }
    },
    TRADERS_GUILD {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            cards.add(new Card(id_sequence++, "Traders Guild", CardType.GUILD, this).setCostResource(Resource.CLOTH, Resource.PAPYRUS, Resource.GLASS));
            return cards;
        }

        void awardBonus(Player player) {
            for (Player neighbor : Game.myGame.getNeighbors(player)) {
                player.addVictoryPoints(VictoryPointCategory.GUILD, neighbor.getCardCount(CardType.COMMERCIAL));
            }
        }
    },
    PHILOSOPHERS_GUILD {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            cards.add(new Card(id_sequence++, "Philosophers Guild", CardType.GUILD, this).setCostResource(Resource.CLAY, Resource.CLAY, Resource.CLAY,
                Resource.CLOTH, Resource.PAPYRUS));
            return cards;
        }

        void awardBonus(Player player) {
            for (Player neighbor : Game.myGame.getNeighbors(player)) {
                player.addVictoryPoints(VictoryPointCategory.GUILD, neighbor.getCardCount(CardType.SCIENTIFIC));
            }
        }
    },
    SPIES_GUILD {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            cards.add(new Card(id_sequence++, "Spies Guild", CardType.GUILD, this).setCostResource(Resource.CLAY, Resource.CLAY, Resource.CLAY, Resource.GLASS));
            return cards;
        }

        void awardBonus(Player player) {
            for (Player neighbor : Game.myGame.getNeighbors(player)) {
                player.addVictoryPoints(VictoryPointCategory.GUILD, neighbor.getCardCount(CardType.MILITARY));
            }
        }
    },
    STRATEGISTS_GUILD {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            cards.add(new Card(id_sequence++, "Strategists Guild", CardType.GUILD, this).setCostResource(Resource.ORE, Resource.ORE, Resource.STONE,
                Resource.CLOTH));
            return cards;
        }

        void awardBonus(Player player) {
            for (Player neighbor : Game.myGame.getNeighbors(player)) {
                player.addVictoryPoints(VictoryPointCategory.GUILD, neighbor.getMilitaryTokenCount(-1));
            }
        }
    },
    SHIPOWNERS_GUILD {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            cards.add(new Card(id_sequence++, "Shipowners Guild", CardType.GUILD, this).setCostResource(Resource.WOOD, Resource.WOOD, Resource.WOOD,
                Resource.PAPYRUS, Resource.GLASS));
            return cards;
        }

        void awardBonus(Player player) {
            player.addVictoryPoints(VictoryPointCategory.GUILD, player.getCardCount(CardType.RAW_MATERIALS));
            player.addVictoryPoints(VictoryPointCategory.GUILD, player.getCardCount(CardType.MANUFACTURED_GOODS));
            player.addVictoryPoints(VictoryPointCategory.GUILD, player.getCardCount(CardType.GUILD));
        }
    },
    SCIENTISTS_GUILD {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            cards.add(new Card(id_sequence++, "Scientists Guild", CardType.GUILD, this).setCostResource(Resource.WOOD, Resource.WOOD, Resource.ORE,
                Resource.ORE, Resource.PAPYRUS));
            return cards;
        }

        void awardBonus(Player player) {
            player.addScience(Science.CHOOSE);
        }
    },
    MAGISTRATES_GUILD {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            cards.add(new Card(id_sequence++, "Magistrates Guild", CardType.GUILD, this).setCostResource(Resource.WOOD, Resource.WOOD, Resource.WOOD,
                Resource.STONE, Resource.CLOTH));
            return cards;
        }

        void awardBonus(Player player) {
            for (Player neighbor : Game.myGame.getNeighbors(player)) {
                player.addVictoryPoints(VictoryPointCategory.GUILD, neighbor.getCardCount(CardType.CIVILIAN));
            }
        }
    },
    BUILDERS_GUILD {
        List<Card> generateCards(int age, int numPlayers) {
            List<Card> cards = new ArrayList<Card>();
            cards.add(new Card(id_sequence++, "Builders Guild", CardType.GUILD, this).setCostResource(Resource.STONE, Resource.STONE, Resource.CLAY,
                Resource.CLAY, Resource.GLASS));
            return cards;
        }

        void awardBonus(Player player) {
            for (WonderPhase wonderPhase : player.getCity()
                .getWonderPhasesForSide()) {

                if (wonderPhase.isCompleted()) {
                    player.addVictoryPoints(VictoryPointCategory.WONDER, 1);
                }
            }

            for (Player neighbor : Game.myGame.getNeighbors(player)) {
                for (WonderPhase wonderPhase : neighbor.getCity()
                    .getWonderPhasesForSide()) {

                    if (wonderPhase.isCompleted()) {
                        player.addVictoryPoints(VictoryPointCategory.WONDER, 1);
                    }
                }
            }
        }
    };

    private static int id_sequence = 1;

    abstract List<Card> generateCards(int age, int numPlayers);

    abstract void awardBonus(Player player);
}
